package com.ruoyi.framework.aspectj;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author wq
 * @date 2022/10/9 11:15
 */
@Component
@Aspect
@Slf4j
public class RequestParameterAop {


    @Pointcut("execution(public * com.ruoyi.module.*.controller..*.*(..))")
    public void controllerLog() {
    }

    @Around("controllerLog()")
    public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result;
        Stopwatch stopwatch = Stopwatch.createStarted();
        result = joinPoint.proceed();
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            // ip地址
            String ipAddr = getRemoteHost(request);
            // 请求路径
            String requestUrl = request.getRequestURL().toString();
            // 获取请求参数进行打印
            Signature signature = joinPoint.getSignature();
            // 构造参数组集合
            List<Object> argList = new ArrayList<>();
            for (Object arg : joinPoint.getArgs()) {
                // request/response无法使用toJSON
                if (arg instanceof HttpServletRequest) {
                    argList.add("request");
                } else if (arg instanceof HttpServletResponse) {
                    argList.add("response");
                } else {
                    argList.add(JSON.toJSON(arg));
                }
            }
            stopwatch.stop();
            long timeConsuming = stopwatch.elapsed(TimeUnit.MILLISECONDS);
            log.error("\n{ \n请求源IP:【{}】 \n请求URL:【{}】 \n请求方式:【{}】 \n请求参数:{} \n响应结果:{} \n请求耗时:【{}】毫秒 \n}",
                    ipAddr,
                    requestUrl,
                    request.getMethod(),
                    JSON.toJSON(argList),
                    JSON.toJSON(result),
                    timeConsuming);
        } catch (Exception e) {
            log.error("参数获取失败: {}", e.getMessage());
        }
        return result;
    }

    /**
     * 获取目标主机的ip
     *
     * @param request request
     * @return String
     */
    private String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.contains("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }

}
